﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2013-09-28 18:00
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using BassDrop.Core.Common.Data.IO.Portable;
using BassDrop.Core.Common.Exceptions;

namespace BassDrop.Plugins.NAudioDecoder.Localization
{
	/// <summary>
	/// Class containing the strings used in the program
	/// </summary>
	public static partial class PluginStrings
	{
		/// <summary>
		/// Reports property changes for WPF bindings
		/// </summary>
		public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged; // NOTICE: do not change the name, it breaks the behaviour

		/// <summary>
		/// The currently selected language, which this class contains the localization for
		/// </summary>
		public static PluginLanguage SelectedLanguage
		{
			get;
			private set;
		}


		/// <summary>
		/// Loads the strings for the specified language
		/// </summary>
		/// <param name="language"></param>
		/// <param name="fileHandler">file handler object providing file handling on the current platform</param>
		public static void LoadStringsFor( PluginLanguage language, IFileHandler fileHandler )
		{
			SelectedLanguage = language;

			if ( SelectedLanguage.LanguageFilePath != null )
			{
				try
				{
					using ( var stream = fileHandler.GetStream( SelectedLanguage.LanguageFilePath.LocalPath, PortableFileMode.Open, PortableFileAccess.Read, PortableFileShare.Read ) )
					{
						XDocument doc = XDocument.Load( stream );
						XElement strings = doc.Descendants( "Strings" ).FirstOrDefault();

						LoadStrings( strings );
					}
				}
				catch ( Exception e )
				{
					// set defaults
					LoadStrings( new XElement( "Strings", null ) );
					throw new DataFormatException( PluginStrings.ExceptionFailedToLoadStrings, e );
				}
			}
			else
			{
				LoadStrings( new XElement( "Strings", null ) );
			}
		}

		/// <summary>
		/// Loads the strings from the xml element
		/// </summary>
		/// <param name="strings">the xml node containing the localized strings</param>
		private static void LoadStrings( XElement strings )
		{
			LoadExceptionStrings( strings );
			LoadDescriptionStrings( strings );

			if ( StaticPropertyChanged != null )
				StaticPropertyChanged( null, new PropertyChangedEventArgs( "PluginStrings" ) ); // notify bindings
		}

		/// <summary>
		/// Sets the value of a property reading it from the children of the passed XElement.
		/// If the value cannot be found, a default is used.
		/// </summary>
		/// <param name="valueSource">the xml element containing the values</param>
		/// <param name="propertyName">the name of the property to set</param>
		/// <param name="defaultValue">the default value of the property</param>
		private static void SetProperty( XElement valueSource, string propertyName, string defaultValue )
		{
#if DEBUG
			defaultValue = "#" + defaultValue ?? "{MISSING}";
#endif // DEBUG

			string value =
				(valueSource.Descendants( propertyName )
					.FirstOrDefault()
					?? new XElement( propertyName, defaultValue )) // if the element is null, mock one with the default value
						.Value.Trim();

			typeof( PluginStrings ).GetProperty( propertyName ).SetValue( null, value, null );

			if ( StaticPropertyChanged != null )
				StaticPropertyChanged( null, new PropertyChangedEventArgs( propertyName ) ); // notify bindings
		}
	}
}
